package draft

import (
	"archive/zip"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/user/go-capcut/internal/config"
	"github.com/user/go-capcut/internal/util"
)

// Exporter 草稿导出器
type Exporter struct {
	Config *config.Config
}

// NewExporter 创建新的导出器
func NewExporter(cfg *config.Config) *Exporter {
	return &Exporter{
		Config: cfg,
	}
}

// ExportDraft 导出草稿为剪映/CapCut可识别的格式
func (e *Exporter) ExportDraft(draft *Draft, outputPath string) (string, error) {
	// 创建临时目录
	tempDir, err := os.MkdirTemp("", "capcut-draft-*")
	if err != nil {
		return "", fmt.Errorf("创建临时目录失败: %w", err)
	}
	defer os.RemoveAll(tempDir)

	// 创建草稿目录结构
	draftDir := filepath.Join(tempDir, draft.ID)
	err = os.MkdirAll(draftDir, 0755)
	if err != nil {
		return "", fmt.Errorf("创建草稿目录失败: %w", err)
	}

	// 复制模板文件
	err = e.copyTemplateFiles(draftDir)
	if err != nil {
		return "", fmt.Errorf("复制模板文件失败: %w", err)
	}

	// 生成草稿文件
	err = e.generateDraftFiles(draft, draftDir)
	if err != nil {
		return "", fmt.Errorf("生成草稿文件失败: %w", err)
	}

	// 打包为zip文件
	outputZipPath := outputPath
	if !strings.HasSuffix(outputZipPath, ".zip") {
		outputZipPath = filepath.Join(outputPath, fmt.Sprintf("%s.zip", draft.ID))
	}

	err = e.zipDirectory(tempDir, outputZipPath)
	if err != nil {
		return "", fmt.Errorf("打包草稿文件失败: %w", err)
	}

	return outputZipPath, nil
}

// copyTemplateFiles 复制模板文件到草稿目录
func (e *Exporter) copyTemplateFiles(draftDir string) error {
	// 模板目录
	templateDir := "./template"

	// 复制模板文件
	return filepath.Walk(templateDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 计算相对路径
		relPath, err := filepath.Rel(templateDir, path)
		if err != nil {
			return err
		}

		// 目标路径
		dstPath := filepath.Join(draftDir, relPath)

		// 如果是目录，创建目录
		if info.IsDir() {
			return os.MkdirAll(dstPath, 0755)
		}

		// 复制文件
		return copyFile(path, dstPath)
	})
}

// generateDraftFiles 生成草稿文件
func (e *Exporter) generateDraftFiles(draft *Draft, draftDir string) error {
	// 生成draft_info.json
	err := e.generateDraftInfo(draft, draftDir)
	if err != nil {
		return err
	}

	// 生成draft_content.json
	err = e.generateDraftContent(draft, draftDir)
	if err != nil {
		return err
	}

	// 生成materials.json
	return e.generateMaterials(draft, draftDir)
}

// generateDraftInfo 生成草稿信息文件
func (e *Exporter) generateDraftInfo(draft *Draft, draftDir string) error {
	// 草稿信息
	draftInfo := map[string]interface{}{
		"draft_id":       draft.ID,
		"draft_name":     draft.Name,
		"draft_version":  "1.0.0",
		"create_time":    time.Now().Unix(),
		"last_modified":  time.Now().Unix(),
		"resolution":     map[string]int{"width": draft.Width, "height": draft.Height},
		"fps":           30,
		"duration":       draft.Duration,
		"track_count":    len(draft.Tracks),
		"segment_count":  countSegments(draft),
		"is_capcut_env":  e.Config.IsCapcutEnv,
		"draft_domain":   e.Config.DraftDomain,
		"preview_router": e.Config.PreviewRouter,
	}

	// 写入文件
	return writeJSONFile(filepath.Join(draftDir, "draft_info.json"), draftInfo)
}

// generateDraftContent 生成草稿内容文件
func (e *Exporter) generateDraftContent(draft *Draft, draftDir string) error {
	// 构建轨道数据
	tracks := make([]map[string]interface{}, 0)
	
	// 辅助函数处理单个轨道
	processTrack := func(track Track, tracksPtr *[]map[string]interface{}) {
		// 构建片段数据
		segments := make([]map[string]interface{}, 0, len(track.Segments))
		for _, segment := range track.Segments {
			// 基本片段数据
			segmentData := map[string]interface{}{
				"id":         segment.ID,
				"material_id": segment.MaterialID,
				"start":      segment.Start,
				"end":        segment.End,
				"target_start": segment.TargetStart,
				"volume":     segment.Volume,
			}

			// 根据轨道类型添加特定数据
			switch track.Type {
			case "video":
				if path, ok := segment.ExtraParams["path"]; ok {
					segmentData["path"] = path
				}
			case "audio":
				if path, ok := segment.ExtraParams["path"]; ok {
					segmentData["path"] = path
				}
			case "text":
				segmentData["text"] = segment.Text
				segmentData["font_color"] = segment.FontColor
				segmentData["font_size"] = segment.FontSize
				segmentData["font_name"] = segment.FontName
			case "image":
				if path, ok := segment.ExtraParams["path"]; ok {
					segmentData["path"] = path
				}
			}

			// 添加特效
			if len(segment.Effects) > 0 {
				effects := make([]map[string]interface{}, 0, len(segment.Effects))
				for _, effect := range segment.Effects {
					effectData := map[string]interface{}{
						"id":   effect.ID,
						"type": effect.Type,
					}
					
					// 从Params中获取额外信息
					if name, ok := effect.Params["name"]; ok {
						effectData["name"] = name
					}
					if startTime, ok := effect.Params["start_time"]; ok {
						effectData["start_time"] = startTime
					}
					if endTime, ok := effect.Params["end_time"]; ok {
						effectData["end_time"] = endTime
					}

					// 添加关键帧
					if len(effect.Keyframes) > 0 {
						keyframes := make([]map[string]interface{}, 0, len(effect.Keyframes))
						for _, keyframe := range effect.Keyframes {
							keyframeData := map[string]interface{}{
								"time":  keyframe.Time,
								"value": keyframe.Value,
							}
							keyframes = append(keyframes, keyframeData)
						}
						effectData["keyframes"] = keyframes
					}

					effects = append(effects, effectData)
				}
				segmentData["effects"] = effects
			}

			segments = append(segments, segmentData)
		}

		// 构建轨道数据
		trackData := map[string]interface{}{
			"id":       track.ID,
			"name":     track.Name,
			"type":     track.Type,
			"segments": segments,
		}
		*tracksPtr = append(*tracksPtr, trackData)
	}
	
	// 处理所有类型的轨道
	for _, track := range draft.VideoTracks {
		processTrack(track, &tracks)
	}
	for _, track := range draft.AudioTracks {
		processTrack(track, &tracks)
	}
	for _, track := range draft.TextTracks {
		processTrack(track, &tracks)
	}
	for _, track := range draft.ImageTracks {
		processTrack(track, &tracks)
	}

	// 草稿内容
	draftContent := map[string]interface{}{
		"draft_id":  draft.ID,
		"tracks":    tracks,
		"width":     draft.Width,
		"height":    draft.Height,
		"duration":  calculateDuration(draft),
		"fps":       30,
	}

	// 写入文件
	return writeJSONFile(filepath.Join(draftDir, "draft_content.json"), draftContent)
}

// generateMaterials 生成素材文件
func (e *Exporter) generateMaterials(draft *Draft, draftDir string) error {
	// 收集素材
	materials := make(map[string]interface{})
	videos := make([]map[string]interface{}, 0)
	audios := make([]map[string]interface{}, 0)
	images := make([]map[string]interface{}, 0)
	texts := make([]map[string]interface{}, 0)

	// 处理视频轨道
	for _, track := range draft.VideoTracks {
		for _, segment := range track.Segments {
			if path, ok := segment.ExtraParams["path"]; ok {
				pathStr, _ := path.(string)
				videos = append(videos, map[string]interface{}{
					"id":   segment.ID,
					"path": pathStr,
					"name": util.GetFileName(pathStr),
				})
			}
		}
	}
	
	// 处理音频轨道
	for _, track := range draft.AudioTracks {
		for _, segment := range track.Segments {
			if path, ok := segment.ExtraParams["path"]; ok {
				pathStr, _ := path.(string)
				audios = append(audios, map[string]interface{}{
					"id":   segment.ID,
					"path": pathStr,
					"name": util.GetFileName(pathStr),
				})
			}
		}
	}
	
	// 处理图片轨道
	for _, track := range draft.ImageTracks {
		for _, segment := range track.Segments {
			if path, ok := segment.ExtraParams["path"]; ok {
				pathStr, _ := path.(string)
				images = append(images, map[string]interface{}{
					"id":   segment.ID,
					"path": pathStr,
					"name": util.GetFileName(pathStr),
				})
			}
		}
	}
	
	// 处理文本轨道
	for _, track := range draft.TextTracks {
		for _, segment := range track.Segments {
			texts = append(texts, map[string]interface{}{
				"id":        segment.ID,
				"text":      segment.Text,
				"font_name": segment.FontName,
				"font_size": segment.FontSize,
				"font_color": segment.FontColor,
			})
		}
	}

	materials["videos"] = videos
	materials["audios"] = audios
	materials["images"] = images
	materials["texts"] = texts

	// 写入文件
	return writeJSONFile(filepath.Join(draftDir, "materials.json"), materials)
}

// zipDirectory 将目录打包为zip文件
func (e *Exporter) zipDirectory(sourceDir, zipPath string) error {
	// 创建zip文件
	zipFile, err := os.Create(zipPath)
	if err != nil {
		return err
	}
	defer zipFile.Close()

	// 创建zip写入器
	zipWriter := zip.NewWriter(zipFile)
	defer zipWriter.Close()

	// 遍历源目录
	return filepath.Walk(sourceDir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		// 创建zip头信息
		header, err := zip.FileInfoHeader(info)
		if err != nil {
			return err
		}

		// 计算相对路径
		relPath, err := filepath.Rel(sourceDir, path)
		if err != nil {
			return err
		}

		// 设置zip文件名
		header.Name = relPath

		// 设置压缩方法
		if info.IsDir() {
			header.Name += "/"
		} else {
			header.Method = zip.Deflate
		}

		// 创建文件写入器
		writer, err := zipWriter.CreateHeader(header)
		if err != nil {
			return err
		}

		// 如果是目录，不需要写入内容
		if info.IsDir() {
			return nil
		}

		// 打开源文件
		file, err := os.Open(path)
		if err != nil {
			return err
		}
		defer file.Close()

		// 复制文件内容到zip
		_, err = io.Copy(writer, file)
		return err
	})
}

// copyFile 复制文件
func copyFile(src, dst string) error {
	// 打开源文件
	srcFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	// 创建目标文件
	dstFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	// 复制内容
	_, err = io.Copy(dstFile, srcFile)
	return err
}

// writeJSONFile 将数据写入JSON文件
func writeJSONFile(path string, data interface{}) error {
	// 创建文件
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()

	// 编码为JSON
	encoder := json.NewEncoder(file)
	encoder.SetIndent("", "  ")
	return encoder.Encode(data)
}

// countSegments 计算草稿中的片段总数
func countSegments(draft *Draft) int {
	count := 0
	for _, track := range draft.VideoTracks {
		count += len(track.Segments)
	}
	for _, track := range draft.AudioTracks {
		count += len(track.Segments)
	}
	for _, track := range draft.TextTracks {
		count += len(track.Segments)
	}
	for _, track := range draft.ImageTracks {
		count += len(track.Segments)
	}
	return count
}

// calculateDuration 计算草稿的总时长
func calculateDuration(draft *Draft) float64 {
	var maxDuration float64 = 0
	
	// 检查所有轨道类型
	checkTrackDuration := func(tracks []Track) {
		for _, track := range tracks {
			for _, segment := range track.Segments {
				segmentEnd := segment.TargetStart + (segment.End - segment.Start) / segment.Speed
				if segmentEnd > maxDuration {
					maxDuration = segmentEnd
				}
			}
		}
	}
	
	checkTrackDuration(draft.VideoTracks)
	checkTrackDuration(draft.AudioTracks)
	checkTrackDuration(draft.TextTracks)
	checkTrackDuration(draft.ImageTracks)
	
	return maxDuration
}
